package demo.java.lang.management.vo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author buffoon
 * @date 16/1/18
 */
public class JvmMetricUtil {
	
	public static List<MetricSpan> getFgcMetric(DynamicJvmModel dynamicJvmModel,long ts) {
		String app = dynamicJvmModel.getAppName();
		String hostname = dynamicJvmModel.getHostname();
		String dataType = XdcsConstants.JVM_DATA_TYPE_KEY;

		List<MetricSpan> metricSpans = new ArrayList<MetricSpan>();
		List<GarbageCollectorInfo> garbageCollectorInfos = dynamicJvmModel.getGarbageCollectorInfos();
		if (garbageCollectorInfos != null && garbageCollectorInfos.size() > 0) {
			for (GarbageCollectorInfo garbageCollectorInfo : garbageCollectorInfos) {
				if (garbageCollectorInfo.getLastFgcTime()>0) {
					MetricSpan metricSpan = newMetricByPair(XdcsConstants.JVM_FGC_METRIC,XdcsConstants.GC_NAME_KEY,garbageCollectorInfo.getName(), dataType,XdcsConstants.GC_DURATION_KEY,garbageCollectorInfo.getLastFgcDuration());
					ts = ts + garbageCollectorInfo.getLastFgcTime();
					metricSpan.setTimestamp(ts);
                    metricSpans.add(metricSpan);
				}
			}
		}
		for (MetricSpan metricSpan : metricSpans) {
			Map<String, String> tags = metricSpan.getTags();
			tags.put(XdcsConstants.TAG_APP, app);
			tags.put(XdcsConstants.TAG_HOST, hostname);
		}
		return metricSpans;
	}

    public static List<MetricSpan> getMetric(DynamicJvmModel dynamicJvmModel) {
        String app = dynamicJvmModel.getAppName();
        String hostname = dynamicJvmModel.getHostname();
        long timestamp = dynamicJvmModel.getTimestamp();
        String dataType = XdcsConstants.JVM_DATA_TYPE_KEY;

        List<MetricSpan> metricSpans = new ArrayList<MetricSpan>();

        JVMClassLoading classLoading = dynamicJvmModel.getClassLoading();
        if (classLoading != null) {
            metricSpans.add(newMetricByPair(XdcsConstants.JVM_CLASSLOAD_METRIC, dataType, XdcsConstants.LOADEDCLASS_COUNT_KEY, classLoading.getLoadedClassCount()));
            metricSpans.add(newMetricByPair(XdcsConstants.JVM_CLASSLOAD_METRIC, dataType, XdcsConstants.TOTAL_LOADEDCLASS_COUNT_KEY, classLoading.getTotalLoadedClassCount()));
            metricSpans.add(newMetricByPair(XdcsConstants.JVM_CLASSLOAD_METRIC, dataType, XdcsConstants.UNLOADED_CLASS_COUNT_KEY, classLoading.getUnloadedClassCount()));
            metricSpans.add(newMetricByPair(XdcsConstants.JVM_CLASSLOAD_METRIC, dataType, XdcsConstants.TOTAL_COMPILATION_TIME_KEY, classLoading.getTotalCompilationTime()));
        }

        List<GarbageCollectorInfo> garbageCollectorInfos = dynamicJvmModel.getGarbageCollectorInfos();
        if (garbageCollectorInfos != null && garbageCollectorInfos.size() > 0) {
            for (GarbageCollectorInfo garbageCollectorInfo : garbageCollectorInfos) {
                metricSpans.add(newMetricByPair(XdcsConstants.JVM_GC_METRIC, XdcsConstants.GC_NAME_KEY, garbageCollectorInfo.getName(), dataType, XdcsConstants.COLLECTION_COUNT_KEY, garbageCollectorInfo.getCollectionCount()));
                metricSpans.add(newMetricByPair(XdcsConstants.JVM_GC_METRIC, XdcsConstants.GC_NAME_KEY, garbageCollectorInfo.getName(), dataType, XdcsConstants.COLLECTION_TIME_KEY, garbageCollectorInfo.getCollectionTime()));
            }
        }

        List<MemoryPool> memoryPools = dynamicJvmModel.getMemoryPools();
        if (memoryPools != null && memoryPools.size() > 0) {
            for (MemoryPool memoryPool : memoryPools) {
                metricSpans.add(newMetricByPair(XdcsConstants.JVM_HEAP_METRIC, XdcsConstants.MEMORYPOOL_NAME_KEY, memoryPool.getName(), dataType, XdcsConstants.USED_KEY, memoryPool.getUsed()));
                metricSpans.add(newMetricByPair(XdcsConstants.JVM_HEAP_METRIC, XdcsConstants.MEMORYPOOL_NAME_KEY, memoryPool.getName(), dataType, XdcsConstants.PEAK_USED_KEY, memoryPool.getPeakUsed()));
                metricSpans.add(newMetricByPair(XdcsConstants.JVM_HEAP_METRIC, XdcsConstants.MEMORYPOOL_NAME_KEY, memoryPool.getName(), dataType, XdcsConstants.MAX_KEY, memoryPool.getMax()));
                metricSpans.add(newMetricByPair(XdcsConstants.JVM_HEAP_METRIC, XdcsConstants.MEMORYPOOL_NAME_KEY, memoryPool.getName(), dataType, XdcsConstants.INIT_KEY, memoryPool.getInit()));
                metricSpans.add(newMetricByPair(XdcsConstants.JVM_HEAP_METRIC, XdcsConstants.MEMORYPOOL_NAME_KEY, memoryPool.getName(), dataType, XdcsConstants.COMMITTED_KEY, memoryPool.getCommitted()));
            }
        }

        JVMProcessStat jvmProcessStat = dynamicJvmModel.getProcessStat();
        if (jvmProcessStat != null) {
            metricSpans.add(newMetricByPair(XdcsConstants.JVM_CPU_METRIC, dataType, XdcsConstants.CPU_RATE_KEY, jvmProcessStat.getCpuRate()));
            metricSpans.add(newMetricByPair(XdcsConstants.JVM_CPU_METRIC, dataType, XdcsConstants.SYSTEM_LOADAVERAGE_KEY, jvmProcessStat.getSystemLoadAverage()));
            metricSpans.add(newMetricByPair(XdcsConstants.JVM_THREAD_METRIC, dataType, XdcsConstants.DAEMON_THREAD_COUNT_KEY, jvmProcessStat.getDaemonThreadCount()));
            metricSpans.add(newMetricByPair(XdcsConstants.JVM_THREAD_METRIC, dataType, XdcsConstants.PEAK_THREAD_COUNT_KEY, jvmProcessStat.getPeakThreadCount()));
            metricSpans.add(newMetricByPair(XdcsConstants.JVM_THREAD_METRIC, dataType, XdcsConstants.THREAD_COUNT_KEY, jvmProcessStat.getThreadCount()));
            metricSpans.add(newMetricByPair(XdcsConstants.JVM_THREAD_METRIC, dataType, XdcsConstants.TIMEDWAITING_THREAD_COUNT_KEY, jvmProcessStat.getTimedWaitingThreadCount()));
            metricSpans.add(newMetricByPair(XdcsConstants.JVM_THREAD_METRIC, dataType, XdcsConstants.WAITING_THREAD_COUNT_KEY, jvmProcessStat.getWaitingThreadCount()));
            metricSpans.add(newMetricByPair(XdcsConstants.JVM_THREAD_METRIC, dataType, XdcsConstants.RUNNABLE_THREAD_COUNT_KEY, jvmProcessStat.getRunnableThreadCount()));
        }

        for (MetricSpan metricSpan : metricSpans) {
            metricSpan.setTimestamp(timestamp);
            Map<String, String> tags = metricSpan.getTags();
            tags.put(XdcsConstants.TAG_APP, app);
            tags.put(XdcsConstants.TAG_HOST, hostname);
        }

        return metricSpans;
    }

    private static MetricSpan newMetricByPair(String metric, String key1, String name1, String key2, String name2, Object value) {
        MetricSpan metricSpan = new MetricSpan();
        metricSpan.setMetric(metric);
        Map<String, String> tags = new HashMap<String, String>();
        tags.put(key1, name1);
        tags.put(key2, name2);
        metricSpan.setTags(tags);
        metricSpan.setValue(value);

        return metricSpan;
    }

    private static MetricSpan newMetricByPair(String metric, String key, String name, Object value) {
        MetricSpan metricSpan = new MetricSpan();
        metricSpan.setMetric(metric);
        Map<String, String> tags = new HashMap<String, String>();
        tags.put(key, name);
        metricSpan.setTags(tags);
        metricSpan.setValue(value);

        return metricSpan;
    }

}
